1

I'm new in TDD developing and I've just started to do some tests with Nunit 3.7.1, Newtonsoft.Json version=10.0.3, JustMock Lite version 2016.2.426.1, C# and .NET Framework 4.7.

I want to test this class:

public class LoadFinishedTrzlBatch
{
    private IGenericRepository<ProductionOrder> proOrdRepository;
    private IGenericRepository<Batch> batchRepository;
    private IGenericRepository<Code> codeRepository;
    private IGenericRepository<Aggregation> aggregationRepository;
    private IGenericRepository<AggregationChildren> aggChildrenRepository;

    public LoadFinishedTrzlBatch(
        IGenericRepository<ProductionOrder> proOrdRepository,
        IGenericRepository<Batch> batchRepository,
        IGenericRepository<Code> codeRepository,
        IGenericRepository<Aggregation> aggregationRepository,
        IGenericRepository<AggregationChildren> aggChildrenRepository)
    {
        this.proOrdRepository = proOrdRepository;
        this.batchRepository = batchRepository;
        this.codeRepository = codeRepository;
        this.aggregationRepository = aggregationRepository;
        this.aggChildrenRepository = aggChildrenRepository;
    }

    public bool ExistsProductionOrder(string productionOrderName)
    {
        if (string.IsNullOrWhiteSpace(productionOrderName))
            throw new ArgumentNullException(nameof(productionOrderName));

        return (
            proOrdRepository
                .SearchFor(p => p.Name == productionOrderName)
                .FirstOrDefault() != null
        );
    }
}

With this test:

[TestFixture]
class LoadFinishedTrzlBatchTest
{
    private LoadFinishedTrzlBatch _load;

    [SetUp]
    public void SetUpLoadFinishedTrzlBatch()
    {
        var proOrdRepository = 
            Mock.Create<IGenericRepository<ProductionOrder>>();
        var batchRepository =
            Mock.Create<IGenericRepository<Batch>>();
        var codeRepository =
            Mock.Create<IGenericRepository<Code>>();
        var aggRepository =
            Mock.Create<IGenericRepository<Aggregation>>();
        var aggChildrenRepository =
            Mock.Create<IGenericRepository<AggregationChildren>>();

        _load = new LoadFinishedTrzlBatch(
            proOrdRepository,
            batchRepository,
            codeRepository,
            aggRepository,
            aggChildrenRepository);
    }

    [Test]
    public void ShouldExistsProductionOrder()
    {
        // Arrange
        Mock.Arrange(() => _load.ExistsProductionOrder("ProOrd"))
            .Returns(true)
            .MustBeCalled();

        // Act
        var actual = _load.ExistsProductionOrder("ProOrd");

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

And finally this is the IGenericRepository:

public interface IGenericRepository<TEntity>
{
    [ OMITTED ]

    IQueryable<TEntity> SearchFor(Expression<Func<TEntity, bool>> predicate);

    [ OMITTED ]
}

First, I'm not sure if this is the right way to test the method LoadFinishedTrzlBatch.ExistsProductionOrder. Everything is new for me with TDD and I'm lost.

I'm confuse of how I have mocked the IGenericRepository<ProductionOrder>. It is always be true and I'm not testing IGenericRepository<ProductionOrder>. Maybe because I'm not testing the repository.

I'm learning and I don't know what I am doing. This is why I have asked this question. I want to test ExistsProductionOrder method.

How can I test ExistsProductionOrder method?

VansFannel
  • 45,055
  • 107
  • 359
  • 626
  • 1
    It's not really clear what you are actually trying to test here. If you are testing the `ExistsProductionOrder` method, then why would you want ot mock it in the first place? – DavidG Aug 04 '17 at 09:53
  • Because I'm learning and I don't know what I am doing. This is why I have asked this question. I want to test `ExistsProductionOrder` method. – VansFannel Aug 04 '17 at 09:55
  • Then you should just be calling it in it's raw form (i.e. not mocked) and only mock the dependencies, and in particular, any methods on those dependencies that are relevant. – DavidG Aug 04 '17 at 09:56
  • @VansFannel can you show `IGenericRepository` so the proper mock can be arranged. Right now assumptions are being made as it is unknown what members the type has – Nkosi Aug 04 '17 at 13:24
  • @Nkosi `IGenericRepository` added. – VansFannel Aug 04 '17 at 14:41
  • @VansFannel then my guess about the expression was accurate. – Nkosi Aug 04 '17 at 15:58

2 Answers2

1

Actually you want to test if the method ExistsProductionOrder does what it´s supposed to do. Thus you shouldn´t mock it. However you want to mock members that are called within that method, e.g any call to IGenericRepository<T>.DoSomething().

However just call it and compare its result with what you expect:

[Test]
public void ShouldExistsProductionOrder()
{
    // Act
    var actual = _load.ExistsProductionOrder("ProOrd");
    Assert.IsTrue(actual);
}

Now when your method looks like this:

bool ExistsProductionOrder() {
    this.proOrdRepository.DoSomething();
    return ...
}

you can replace the call to DoSomething to something different - your mock.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
1

You need to separate the target dependency so that it can be arranged in isolation in the test case. You also do no mock the SUT (Subject under test). You mock its dependencies. In this case you want to mock the generic repository and arrange the method being called. ie SearchFor

Assuming that method takes a expression predicate, you can arrange the mock to expect one and then apply it to a fake collection store to mock an actual data store.

[TestFixture]
public class LoadFinishedTrzlBatchTest {
    private LoadFinishedTrzlBatch sut;
    //need this later so declaring as field.
    private IGenericRepository<ProductionOrder> proOrdRepository;

    [SetUp]
    public void SetUpLoadFinishedTrzlBatch() {  
        //Not using these so they can be declared locally          
        var batchRepository =
            Mock.Create<IGenericRepository<Batch>>();
        var codeRepository =
            Mock.Create<IGenericRepository<Code>>();
        var aggRepository =
            Mock.Create<IGenericRepository<Aggregation>>();
        var aggChildrenRepository =
            Mock.Create<IGenericRepository<AggregationChildren>>();

        //initializing target mock
        proOrdRepository = 
            Mock.Create<IGenericRepository<ProductionOrder>>();

        sut = new LoadFinishedTrzlBatch(
            proOrdRepository,
            batchRepository,
            codeRepository,
            aggRepository,
            aggChildrenRepository);
    }

    [Test]
    public void ShouldExistsProductionOrder()
    {
        // Arrange
        var productionOrderName = "ProOrd";
        var orders = new List<ProductionOrder>() {
            new ProductionOrder { Name = productionOrderName },
            new ProductionOrder { Name = "Dummy for Filter" }
        };
        Mock.Arrange(() => proOrdRepository
            .SearchFor(Arg.IsAny<Expression<Func<ProductionOrder,bool>>>()))
            .Returns((Expression<Func<ProductionOrder,bool>> expression) => 
                orders.Where(expression.Compile()).AsQueryable()
            )
            .MustBeCalled();

        // Act
        var actual = sut.ExistsProductionOrder(productionOrderName);

        // Assert
        Assert.IsTrue(actual);
    }
}
VansFannel
  • 45,055
  • 107
  • 359
  • 626
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • Sorry, I've been on holidays and now I have tested your solution but I get the following error message when I create proOrdRepository: `InvalidOperationException: Some attribute type among NUnit.Framework.TestFixtureSetUpAttribute, nunit.framework,NUnit.Framework.TestFixtureTearDownAttribute, nunit.framework not found`. – VansFannel Aug 29 '17 at 06:15
  • I have asked this question: https://stackoverflow.com/questions/45932110/typeinitializationexception-in-nunit-or-justmock – VansFannel Aug 29 '17 at 07:25
  • @VansFannel move the initialization code into the setup function. – Nkosi Aug 29 '17 at 07:43
  • Thanks but it is in the setup function. I have added the test class with all the code to the other question (but it is mostly the same as your class): https://stackoverflow.com/questions/45932110/typeinitializationexception-in-nunit-or-justmock – VansFannel Aug 29 '17 at 07:47