codebased
codebased

Reputation: 7073

Moq testing repository code

I am confused whether I should do TDD on Repository at all or not. I understand that it is not doing any major operations/ business functionality. However, many are doing testing on Repository as well.

I can understand that it is then actually an Integration testing where the data will be hit directly to the database.

My GenericRepository has got one Insert method:

public virtual bool Insert(TEntity entity)
        {
            var validationResult = this.context.Entry(entity).GetValidationResult();

            if (validationResult.IsValid)
            {
                this.databaseSet.Add(entity);
                return true;
            }
            else
            {
                var errors = new List<DbEntityValidationResult>();
                errors.Add(validationResult);
                throw new DbEntityValidationException(string.Empty, errors);
            }
        }

Now I want to test this method using Moq. The TestInitializer looks like as follows:

[TestInitialize]
        public void Initialize()
        {
            // Arrange.
            this.MockData = new List<Document> 
            { 
                new Document { },
            }.AsQueryable();

            this.MockSet = new Mock<DbSet<Document>>();
            this.MockSet.As<IQueryable<Document>>().Setup(m => m.Provider).Returns(this.MockData.Provider);
            this.MockSet.As<IQueryable<Document>>().Setup(m => m.Expression).Returns(this.MockData.Expression);
            this.MockSet.As<IQueryable<Document>>().Setup(m => m.ElementType).Returns(this.MockData.ElementType);
            this.MockSet.As<IQueryable<Document>>().Setup(m => m.GetEnumerator()).Returns(this.MockData.GetEnumerator());

            var entity = new Mock<DbEntityEntry<Document>>();
            this.MockContext = new Mock<IDbContext>();

            this.MockContext.Setup(m => m.Set<Document>()).Returns(this.MockSet.Object);
            this.Repository = new DocumentRepository(this.MockContext.Object);
        }

My Test Insert is as follows:

[TestMethod]
public void InsertDocument()
{
    var document = new Document()
    {
        Binary = new byte[] { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 },
    };

    Assert.IsTrue(this.Repository.Insert(document));

    var exceptionMessage = string.Empty;
    Assert.IsTrue(this.Repository.Save(out exceptionMessage));
}

Why I want to do a test on repository?

The reason I want is because it has got validate functionality that I can check against the model.

Where is the problem?

I cannot get pass through this.context.Entry(entity) of Insert function, because it returns null.

Even if I have tried to setup mock with

var dbEntity = this.MockContext.Object.Entry(document);

this.MockContext.Setup(m => m.Entry(It.IsAny())).Returns(dbEntity);

it returns NULL exception.

Please advise, if it is just as good as leave the repsitory testing.

Upvotes: 0

Views: 264

Answers (1)

Rafał Łużyński
Rafał Łużyński

Reputation: 7312

There is no need to test repository alone (with mocked database gateway) because repository is just returning ARs (aggregate roots), and ARs should be created with a factory, so better just test factory if you need to.

Testing repository has sense if it's an integration test, so with an actual working database (simple repository implementation that works fast, ie. sqlite).

Remember about testing pyramid testing pyramid

Upvotes: 1

Related Questions