通过服务层使用DbContext模拟单元测试

时间:2013-11-12 14:23:01

标签: c# entity-framework unit-testing nunit dbcontext

我是编写单元测试的初学者,我有一个测试,我正努力工作。我将从解释我正在尝试测试的内容开始。

我正在尝试测试一个在Mvc 4项目中保存消息的方法。该方法称为SaveMessage,如下所示。

namespace ChatProj.Service_Layer
{
    public class UserService : IUserService
    {
        public MessageContext messageContext = new MessageContext();

        public UserService()
        {
            _messageRepository = new MessageRepository(messageContext);
        }

        private  IMessageRepository _messageRepository;

    ->  public void SaveMessage(Message message)
        {
             messageContext.Messages.Add(message);
            _messageRepository.Save();
        }

_messageRepository.Save方法中的SaveMessage已在我的DAL图层MessageRepository中实现,如下所示:

public void Save()
        {
            context.SaveChanges();
        }

这种保存方式似乎有点过于复杂,但我以这种方式构建了项目,因为我不希望服务层(IUserService& UserService)处理可以&应该(我认为)由数据访问层(IMessageRepository& MessageRepository)处理。

现在是棘手的部分。我一直试图了解如何对其进行单元测试。这是我的尝试:

namespace ChatProj.Tests
{
    [TestFixture]
    class MessageRepositoryTests
    {
        [SetUp]
        public void Setup()
        {

        }

        [Test]
    public void SaveMessage_SaveWorking_VerifyUse()
    {
        //Arrange
        var userServiceMock = new Mock<UserService>();
        var message = new Message { MessageID = 0, Name = "Erland", MessageString = "Nunit Test", MessageDate = DateTime.Now };
        var repositoryMock = new Mock<IMessageRepository>();
        var contextMock = new Mock<MessageContext>();
        MessageRepository messageRepository = new MessageRepository(contextMock.Object);
        UserService userService = new UserService();

        //Act
        userService.SaveMessage(message);

        //Assert
        repositoryMock.Verify(m => m.Save());
        userServiceMock.Verify(m => m.SaveMessage(message));
    }
}

我收到此错误:Imgur link,我不太确定如何解决它。我已经尝试过查看其他几个SO帖子,但是我没有让测试工作。

所以我想知道,我如何才能让我的单元测试工作?

2 个答案:

答案 0 :(得分:2)

您应该设置MessageContext属性以返回虚假数据,并且不使用SaveChanges方法进行真正的Db调用。 现在它仍然试图访问真正的数据库。

但您只能设置虚拟属性,或者它是否为接口。

因此,最佳解决方案是从MessageContext中提取接口并将其注入存储库。然后,您可以轻松地模拟IMessageContext接口并强制它返回适当的内存数据。

答案 1 :(得分:1)

看看这两行:

UserService userService = new UserService();

//Act
userService.SaveMessage(message);

您正在创建userService个实例,然后立即保存您的消息。现在跳转到SaveMessage代码。

public void SaveMessage(Message message)
{
     messageContext.Messages.Add(message);
    _messageRepository.Save();
}

好的,现在您正在向messageContext添加内容,然后调用_messageRepository.Save()。但messageContext_messageRepository在哪里实例化?

public MessageContext messageContext = new MessageContext();

public UserService()
{
    _messageRepository = new MessageRepository(messageContext);
}

您在实例化时创建它们。您在测试中创建的模拟没有被使用。您可以考虑将它们作为参数传递给UserService构造函数,而不是在构造函数中创建这些对象的实例。然后,您可以在测试中传入模拟实例。