user2791094
user2791094

Reputation: 11

unit test c# mock interface composed inside another interface

I'm a novice to coding.

I have a class, A:

public class A 
{
    public InterfaceB _b;   

    public A() 
    {  
        _b = new B(); 
    } 

    public string functionA() 
    {
        if(String.IsNullOrEmpty(_b.GetId())) 
            return String.Empty;
        else if(String.IsNullOrEmpty(_b.GetKey())) 
            return String.Empty;
        else  
            return _b.GetToken(); 
    } 
} 

public interface InterfaceB 
{    
    string GetId();   
    string GetKey(); 
    string GetToken();
}

I want to test functionA where I can penetrate into all the three method of interfaceB. In my unit test, I create an instance of class A and when I call it I'm not able to set the behavior of class B.

It keeps hitting the db, however I need it for other test cases.

How do I completely mock this so that I can test the entire logic?

Upvotes: 1

Views: 1938

Answers (2)

Sam
Sam

Reputation: 180

Actually, by using Typemock it's possible to test your method without changing your source code. You will be able to mock B as a future instance before you create an instance of A, then you can just modify B's method behavior.

For example:

[TestMethod,Isolated]
public void AllBMethodReturnStrings_WillReturnSuccess()
{
    // Arrange
    // Mocking future B's instance
    var fakeIB = Isolate.Fake.NextInstance<B>();
    var realA = new A();

    Isolate.WhenCalled(()=> fakeIB.GetId()).WillReturn("fakeID");
    Isolate.WhenCalled(() => fakeIB.GetKey()).WillReturn("fakeKey");
    Isolate.WhenCalled(() => fakeIB.GetToken()).WillReturn("success");

    // Act
    var result = realA.functionA();

    // Assert
    Assert.AreEqual("success", result);
}

Upvotes: 1

Scott Hannen
Scott Hannen

Reputation: 29212

To be able to test A and mock interface InterfaceB you have to write A so that it is not responsible for creating an instance of InterfaceB. Instead it receives an instance of InterfaceB through its constructor.

You'll see this pattern over and over again:

public A() 
{  
    private readonly InterfaceB _b;

    public A(InterfaceB b)
    {
        _b = b;
    }

    public string functionA() 
    {
        if(String.IsNullOrEmpty(_b.GetId())) return String.Empty;
        else if(String.IsNullOrEmpty(_b.GetKey())) return String.Empty;
        else  return _b.GetToken(); 
     } 
} 

This is called dependency injection. It means that a class's dependency is "injected" into it rather than that class creating it. When we inject into the constructor like this we also call it "constructor injection", but commonly it's just "dependency injection." And being able to mock interfaces like what you're asking about is one of the reasons why we use it.

A few key details:

  • Because InterfaceB is passed to the constructor, nothing in A ever "knows" what the actual implementation is. It could be anything. As a result, A is never tied to any concrete implementation. (That's why you can "mock" InterfaceB.)
  • The field _b is readonly. That's not strictly necessary, but it means that _b can only be set from the constructor and never changed again. That emphasizes that A only receives this and uses it. This class never controls what _b is. Whatever creates A determines what that value is.

Now when you're writing a unit test you can create mocked implementations of InterfaceB that do exactly what you want, like

public class MockedInterfaceB : InterfaceB
{
    private string _id;
    private string _key;
    private string _token;

    public MockedInterfaceB(string id, string key, string token);
    {
       _id = id;
       _key = key;
       _token = token;
    }
    public string GetId() {return _id};   
    public string GetKey() {return _key}; 
    public string GetToken() {return _token};
}

And then in your unit test you can use that implementation:

var testA = new A(new MockedInterfaceB("myid","mykey","mytoken"));

You can also use tools like Moq to create those mocks more easily.

When you hear of dependency injection it's often in the context of a dependency injection container like Castle Windsor, Autofac, or Unity. Those are useful tools for helping you to make dependency injection work. They're worth learning about. But dependency injection is really just about how you write the classes, like in the example above where we "inject" the dependency (InterfaceB) into class A.

Upvotes: 4

Related Questions