1

I am new to TDD and I am using a stack of XUnit, AutoFixture, and Moq. I am wondering what the purpose of moq is when your testing a function that makes a call to a Repository which hits the database.

For example:
I have a simple project structure where my BLL references my DAL. In my normal application an IRepository is injected into the ProductBLL.cs. So I see that Moq helps me inject the same repository in my test. (But what is the point if the functions that hit the database don't work?)

My question:
Lets say I am making tests to test my business layer and I want to test functions that call my repository which calls my database in my actual code. If using Moq and no data is returned is it possible to test functions like this? In the examples below sut.GetProducts() returns nothing and in my actual code it hits the database and does return something.

Lets say I have a simple test that does this with Moq:

    [Fact]
    public void TestGetProducts_Manual_Moq()
    {
        // Arrange
        var mockCustomerRepository = new Mock<IProductRepository>();

        var sut = new ProductBLL(mockProductRepository.Object);

        // Act
        var result = sut.GetProducts();

        // Assert
        Assert.True(result.Count > 0);
    }

Here is a simple test using AutoFixture combined with Moq to the fullest: (I would think in this example AutoFixture would at least return 3 rows of dummy data)

    [Fact]
    public void TestGetProducts_AutoMoq()
    {
        // Arrange
        Fixture fixture = new Fixture();

        // Add auto mocking support for Moq
        fixture.Customize(new AutoMoqCustomization());

        var sut = fixture.Create<ProductBLL>();

        // Act
        var result = sut.GetProducts();

        // Assert
        Assert.True(result.Count > 0);
    }
Blake Rivell
  • 13,105
  • 31
  • 115
  • 231

1 Answers1

3

If GetProducts simply calls a repository and do nothing with results it might be debatable if it is worth testing it. However, in general GetProducts might do many other things, for example: filtering, grouping, changing format and many other things.

In this case you may validate much more than only checking if GetProducts returns some results. For example, let's assume that the repository returns objects of type A but GetProducts returns objects of type B. It means that data must be copied from objects of type A to objects of type B. On this occasion some data can be removed, some reformatted etc. Your tests should verify if the final result is correct.

Secondly, GetProducts may use 1, 2 or more methods of the repository. Some of these methods may be used only once and some many times. If so, you may use a mock to verify if methods were used:

  • a correct amount of times
  • in the correct order
  • with correct values of parameters

This and this questions are about verifying a correct order of methods calls in Moq. This question is about verifying a number of calls in Moq. I also strongly suggest to read this tutorial.

Community
  • 1
  • 1
Michał Komorowski
  • 6,198
  • 1
  • 20
  • 24
  • I understand there is no point in testing a function that just makes a simple database call. But lets say I have a really complex business function that has several calls to the repository. How does the test work if the repository is never returning anything? So based on what your saying you wouldn't test a function that returns data. But it is alright to test a function that makes data calls inside of it? – Blake Rivell Jan 22 '16 at 13:29
  • Fake objects are not only used to imitate real objects (in this case they are called stubs), but also to verify if methods are used properly (in this case they are called mocks). In other words you should use a mock object created by Moq to verify what you need. – Michał Komorowski Jan 22 '16 at 13:37
  • So typically I wouldn't be testing a function in the BLL that retrieves data and does something with it. I would be testing a function in the BLL that takes data as a parameter so I can use AutoFixture to create dummy data. Does this make sense? – Blake Rivell Jan 22 '16 at 13:44
  • As to _I wouldn't be testing a function in the BLL that retrieves data and does something with it._ If a function manipulates data it may be worth testing. – Michał Komorowski Jan 22 '16 at 13:47
  • Yes, but I must be missing a concept here. Because in the debugger the code never even gets into CustomerRepository.GetCustomers() function when going through a test. By manipulates data you mean that it accepts the data as a parameter or calls GetCustomers() inside of it to get the data it needs to manipulate? – Blake Rivell Jan 22 '16 at 14:00
  • You are right that _CustomerRepository.GetCustomers()_ is not called because during a test you use a mock that imitates the repository. But you may want to test if _ProductBLL_ uses the repository correctly and it is a goal of using mocks. See the paragraph starting with _Secondly, GetProducts may use 1, 2 or more..._ in my answer. – Michał Komorowski Jan 22 '16 at 14:02
  • I am pretty sure I see the power of moq now. I am just so new to testing that I am not realizing the kinds of functions most want to test. Thanks for all of the help. – Blake Rivell Jan 22 '16 at 14:07