简体   繁体   中英

XUnit how to unit test business object and should I be mocking everything?

I am trying to Unit Test (XUnit) my business object where it takes 2 parameters and do some operation before returning an output.

    public OutPutModel MyBusinessObject(InputModel1 obj1, InputModel2 obj2)
    {
        // Performing some actions here including seding a call
        // to the data access layer to perform some db operation.
        return outPutModel;
    }

In my XUnit I am doing the following

    [Fact]
    public void MyBusinessObject_ReturnsOutPutModel()
    {
        var businessObjectMock = new Mock<IBusinessObject>();
        var obj1 = new Mock<InputModel1>();
        var obj2 = new Mock<InputModel2>();

        var outPutModel = new OutPutModel();

        var result = businessObjectMock.Setup(x => x.MyBusinessObject(obj1.Object, obj2.Object)).Returns(outPutModel);

        result.Equals(outPutModel);
    }

Now, I have a break point set in my Business Object (public OutPutModel MyBusinessObject(InputModel1 obj1, InputModel2 obj2)). Upon running the test, it don't hit the break point but still passing the test. Am, I doing something wrong here? Should I be mocking everything including the business object interface or just mock the parameter objects and call a new instance of business object? PS Forgot to mention, I am aware the factor that it is not a good idea of having db level stuff in business objects. Unfortunately, just consider I don't have a choice.

You are using the mocking framework wrong. You also appear to be trying to mock the system under test.

Rule of thumb, only mock what is absolutely necessary and only if using the implementation has knock on effects

If for example the BusinessObject had a dependency on the data access layer like you indicated in the code comments,

public class BusinessObject: IBusinessObject{

    private readonly IDataAccess dataAccess;

    public BusinessObject(IDataAccess dataAccess) {
        this.dataAccess = dataAccess;
    }

    public OutPutModel SomeBusinessMethod(InputModel1 obj1, InputModel2 obj2) {
        // Performing some actions here including seding a call
        // to the data access layer to perform some db operation.
        var outPutModel = dataAccess.SomeMethod(obj1, obj2);

        return outPutModel;
    }
}

you would mock the dependency as it is used in the method under test and then invoke an actual instance of the class under test.

For example

[Fact]
public void MyBusinessObject_ReturnsOutPutModel() {
    //Arrange
    var expected = new OutPutModel {
        // populate as needed
    }
    //mock the dependency
    var dataAccessMock = new Mock<IDataAccess>();
    //Setup the mocked dependency
    dataAccessMock
        .Setup(_ => _.SomeMethod(It.IsAny<InputModel1>(), It.IsAny<InputModel2>()))
        .Returns(expected);
    //inject the dependency into the subject under test
    var businessObject = new BusinessObject(dataAccessMock.Object);
    //needed objects for the test
    var obj1 = new InputModel1 {
        //populate as needed
    };
    var obj2 = new InputModel2 {
        //populate as needed
    };

    //Act
    var actual = businessObject.SomeBusinessMethod(obj1, obj2);

    //Assert
    Assert.AreEqual(expected, actual);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM