0

I have a simple "Get" method. Ex:

public class Foo : IFoo
{
    public Dictionary<string,string> GetSomething(string xyz)
    {
        var result = new Dictionary<string,string>
        ... Go to DB and return some key value pairs
        return result;
    }
}

I wrote a simple test that execute and passes successfully but I'm not getting code coverage on the method.

[TestMethod()]
    public void GetSomething()
    {
        var target = new StubIFoo();

        var expected = new Dictionary<string, string> 
        {
            {"blahKey","blahValue"}
        };

        var results = target.GetSomethingString = s =>
        {
            var result = new Dictionary<string, string> {{"a", "b"}};
            return result;
        };

        var actual = results("a");

        CollectionAssert.AreEqual(expected,actual);
    }

I also tried to target the class itself, which provides the coverage but doesn't return any results (ex: "var target = new StubFoo();")

Again, it successfully executes and passes but I'm not getting any coverage. Any pointers would be appreciated. Thanks.

user3219570
  • 197
  • 1
  • 2
  • 10
  • What coverage are you expecting? What is the relationship between `StubFoo` and `Foo`? – Paolo Jan 21 '14 at 14:24
  • What are you trying to test? `Foo` or something else? If you're trying to test `Foo`, why are you stubbing out `GetSomething`? (Basically you can't expect coverage on a method you're deliberately stubbing out - you're not executing that code!) – Jon Skeet Jan 21 '14 at 14:25
  • Show the code for your stubs. – Haney Jan 21 '14 at 14:26
  • 1
    Also note, that it looks like you have a dependancy to your db in Foo. So you should write a mock db obejct to pass to the Foo instance if you are trying to unit test Foo. – Janne Matikainen Jan 21 '14 at 14:32
  • @JanneMatikainen Thats exactly what I'm shooting for. I know stubbing GetSomething() will get me the coverage but I was a little confused on using a "shim" to fake the DB call. – user3219570 Jan 21 '14 at 14:41

3 Answers3

2

Foo.GetSomething() has 0 code coverage, because you never call it in your test. Instead, you call StubIFoo.GetSomething().

Change var target = new StubIFoo(); into var target = new Foo();, remove the code initializing StubIFoo and you will get some coverage.

Stubs are there to prevent you from using (and testing) the real class. But you must not use a stub of the class you are testing !

krimog
  • 1,257
  • 11
  • 25
  • Thanks. I had that originally but couldn't figure out how to remove the db dependency. Looks like I'll have to stub "GetSomething" and "shim" the DB call. – user3219570 Jan 21 '14 at 14:42
  • If you want to remove the DB Dependency, you need to Stub the DB classes (IDbConnection, IDbCommand...) or for your DB layer you use in the Foo.GetSomething() method. To do so, you can, for example, use dependency injection (in short, when, in your program, you want a IDbConnection, it gives you an SqlConnection and when you want a IDbConnection in your test, it gives you a StubIDbConnection) – krimog Jan 21 '14 at 14:50
  • @user3219570: You don't need to stub Foo, but shimming the DB call should work. It can be messy, though. You should probably do what krimog is suggesting. – Magus Jan 22 '14 at 15:54
0

In your test you are not calling the method GetSomething, but instead are setting a value to the property GetSomethingString.

// Here is the problem. This:
var results = target.GetSomethingString = s =>
{
    var result = new Dictionary<string, string> {{"a", "b"}};
    return result;
};
// Is equal to this:
var lambda = s =>
{
    var result = new Dictionary<string, string> {{"a", "b"}};
    return result;
};
var results2 = target.GetSomethingString = lambda;
ANeves
  • 6,219
  • 3
  • 39
  • 63
  • I changed it up to my original test but while it covers the code, actual doesn't return anything (trying to avoid db dependency). var target = new StubFoo(); var expected = new Dictionary { {"a","b"} }; var actual = target.GetSomething("a"); CollectionAssert.AreEqual(expected,actual); – user3219570 Jan 21 '14 at 14:37
0

Here is general idea what you should do

public class Foo : IFoo
{
    IDbAccess db;

    // Pass the interface, do pass parameters to create it inside constructor
    public Foo(IDbAccess db)
    {
        this.db = db; 
    }

    public Dictionary<string,string> GetSomething(string xyz)
    {
        var result = new Dictionary<string,string>

        // ... Go to DB and return some key value pairs
        result.Add(db.MethodWhatever(xyz));

        return result;
    }
}

[TestMethod()]
public void GetSomething()
{
    var dbMock = new DatabaseMock(); // This implements IDbAccess
    var target = new Foo(dbMock);

    var expected = new Dictionary<string, string> 
    {
        {"blahKey","blahValue"}
    };

    // get something
    var results = target.GetSomething("xyzstring");

    // verify results
    var actual = results.whatever;

    CollectionAssert.AreEqual(expected,actual);
}
Janne Matikainen
  • 5,061
  • 15
  • 21
  • Hey Janne - I appreciate your time and fast response. I'm not certain I know how to "stub/mock" IDbCommand (I'm assuming your IDbAccess is an interface inheriting from it) without implementing all its members. – user3219570 Jan 22 '14 at 15:57
  • You dont stub/mock IDbCommand. You just create a interface so that you can create a mock object to act as your database access. Like your actual db instance should also implement the save IDbAccess interface as the DatabaseMock which will just return the data you would except. If Foo.GetSomething will create DbCommand and execute it then you need to get rid of the dependancy by refactoring it so that you have class which will implement the dataacceess methods you need. – Janne Matikainen Jan 23 '14 at 09:08