How to drown SingleOrDefault with rhinos

It’s hard for me to understand if I have the right approach. I want to test the repository. The repository depends on the DbContext. I want to make sure that the repository does not call the Add function to a property of type IDbSet, which is a member of DbContext.

I tried two approaches. Check with behavior and check condition. It seems that a validation check would be correct, because who knows what the shaded state is doing in a fake object.

    public void VerifyBehaviour()
    {
        // Arrange
        var stubEntities = MockRepository.GenerateStub<IWsStatContext>();
        var stubManufcturers = MockRepository.GenerateStub<IDbSet<Manufacturer>>();
        var manufacturer = new Manufacturer() { Name = "Dummy" };
        var manufacturers = new List<Manufacturer>();
        manufacturers.Add(manufacturer);

        stubManufcturers.Stub(x => x.Local).Return(new System.Collections.ObjectModel.ObservableCollection<Manufacturer>(manufacturers));
        stubManufcturers.Stub(x => x.SingleOrDefault(m => m.Name == "Dummy")).Return(manufacturer);
        stubEntities.Manufacturers = stubManufcturers;

        // Act
        var sut = new EquiptmentRepository(stubEntities);
        sut.AddManufacturer(manufacturer);

        // Assert
        stubManufcturers.AssertWasNotCalled(x => x.Add(manufacturer));
    }


    public void VerifyState()
    { 
        // Arrange
        var stubEntities = MockRepository.GenerateStub<IWsStatContext>();
        var stubManufacturers = new InMemoryDbSet<Manufacturer>();
        var manufacturer = new Manufacturer() { Name = "Dummy" };
        stubManufacturers.Add(manufacturer);
        stubEntities.Manufacturers = stubManufacturers;

        // Act
        var sut = new EquiptmentRepository(stubEntities);
        sut.AddManufacturer(manufacturer);

        // Assert
        Assert.AreEqual(stubManufacturers.Count(), 1);
    }

, NullReferenceExceptions SingleOrDefault. , DbSet. . , , ( , ).

- , SingleOrDefault, , Add ? , Add non-rhinomocked stub.

+3
3

jimmy_keen answer:

SingleOrDefault - , IEnumerable<T> ( IDbSet<T>). , . RhinoMocks ( ) / .

, "" , , : IEnumerable<T>

stubManufcturers.Stub( x => x.GetEnumerator() ).Return( new List<Manufacturer> { manufacturer }.GetEnumerator() );

GetEnumerator() SingleOrDefault, , .

+3

SingleOrDefault - , IEnumerable<T> ( IDbSet<T>). , . RhinoMocks ( ) mock/stub static methods.

, : , ( , , - SingleOrDefault).

: :

-, , , . , , IDbSet:

public class EquiptmentRepository
{
    public void Add(Manufacturer m)
    {
        // perform some local logic before calling IDbSet.Add
        this.AddToDbSet(m);
    }

    protected virtual AddToDbSet(Manufacturer m)
    {
        this.context.Manfuacturers.Add(m);
    }
}

, EquiptmentRepository AddToDbSet, , , :

internal void TestableEquiptmentRepository: EquiptmentRepository
{
    internal List<Manufacturer> AddedManufacturers = new List<Manufacturer>();

    protected override void AddToDbSet(Manufacturer m)
    {
        // we're no longer calling DbSet.Add but kind of rolling
        // our own basic mock and tracking what objects were
        // add by simply adding them to internal list
        this.AddedManufacturers.Add(m);
    }
}

Add, , DbSet . :

[Test]
public void AddManufacturer_DoesNotAddExistingManufacturersToDbSet()
{
    // Arrange
    var stubEntities = MockRepository.GenerateStub<IWsStatContext>();
    var stubManufacturers = MockRepository.GenerateStub<IDbSet<Manufacturer>>();
    var manufacturer = new Manufacturer() { Name = "Dummy" };
    stubManufacturers.Add(manufacturer);
    stubEntities.Manufacturers = stubManufacturers;

    // Act
    var sut = new TestableEquiptmentRepository(stubEntities);
    sut.AddManufacturer(manufacturer);

    // Assert
    Assert.AreEqual(sut.AddedManufacturers.Count(), 0);
}

, EquiptmentRepository.Add DbSet .

+1

RhinoMocks Moq (TypeMock ).

, .

, ( , ). System.Linq.Enumerable :

var item = items.MyExtensions().SingleOrDefault();

, , , :

  • . . , DateTime.Today Foo(DateTime date).
  • Wrap static calls in a non-stationary object. For instance. if I need to get some configuration parameters, instead of calling ConfigurationManager.AppSettings["foo"], I create a non-static class BarConfigurationthat delegates all the work to the static ConfigurationManager (and implements the interface IBar { int Foo { get; }).
  • Do not scoff at it. It looks like I'm testing something that I should not test (Enumerable extensions, Log, etc.)

Consider that you are not testing your repositories. Integration testing for data access logic makes much more sense.

0
source

All Articles