简体   繁体   English

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

[英]Unit Testing with DbContext mock through Service Layer

I'm a beginner at writing unit tests and I have a test I'm trying to get working. 我是编写单元测试的初学者,并且我正在尝试进行一项测试。 I'll start of by explaining what I'm trying to test. 我将从解释我要测试的内容开始。

I'm trying to test a method which saves messages in a Mvc 4 project. 我正在尝试测试一种将消息保存在Mvc 4项目中的方法。 The method is called SaveMessage and is shown below. 该方法称为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();
        }

The _messageRepository.Save in the SaveMessage method is implemented in my DAL layer MessageRepository and looks like this: SaveMessage方法中的_messageRepository.Save在我的DAL层MessageRepository实现,如下所示:

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

This way of saving will seem a bit overcomplicated, but I structured the project this way because I didn't want the service layer ( IUserService & UserService ) to handle operations that could & should (i think) be handled by the Data Access Layer ( IMessageRepository & MessageRepository ). 这种保存方式似乎有些复杂,但是我以这种方式构造项目,因为我不希望服务层( IUserServiceUserService )处理可以并且应该(我认为)由数据访问层( IMessageRepositoryMessageRepository )。

Now comes the tricky part. 现在是棘手的部分。 I've been trying to understand how I could unit test this. 我一直在试图了解如何对此进行单元测试。 This is my try: 这是我的尝试:

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));
    }
}

I get this error: Imgur link , and I'm not quite sure how to solve it. 我收到此错误: Imgur link ,但我不确定如何解决。 I've tried looking at several other SO posts but I fail to make the test work. 我尝试查看其他SO帖子,但无法进行测试。

So I'm wondering, how do I practically get my Unit Test to work? 所以我想知道,如何才能使我的单元测试正常工作?

You should setup your MessageContext properties to return fake data and don't make real Db call with SaveChanges method. 您应该设置MessageContext属性以返回假数据,并且不要使用SaveChanges方法进行真正的Db调用。 Right now it still tries to access a real DB. 现在,它仍然尝试访问真实的数据库。

But you can setup only virtual properties or if it will be an inteface. 但是您只能设置虚拟属性,也可以设置虚拟接口。

So the best solution is to extract an interface from your MessageContext and inject it into repository. 因此,最好的解决方案是从MessageContext提取接口并将其注入存储库。 Then you can easily mock your IMessageContext interface and force it to return appropriate in-memory data. 然后,您可以轻松模拟IMessageContext接口并强制其返回适当的内存中数据。

Take a look at these two lines: 看一下这两行:

UserService userService = new UserService();

//Act
userService.SaveMessage(message);

You're creating a userService instance, and then immediately saving your message. 您正在创建一个userService实例,然后立即保存您的消息。 Now jump into the SaveMessage code. 现在跳到SaveMessage代码。

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

Ok, now you're adding stuff to messageContext , and then calling _messageRepository.Save() . 好的,现在您将内容添加到messageContext ,然后调用_messageRepository.Save() But where are messageContext and _messageRepository instantiated? 但是messageContext_messageRepository在哪里实例化?

public MessageContext messageContext = new MessageContext();

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

You're creating them at instantiation. 您正在实例化时创建它们。 The mocks that you've created in your test aren't being used. 您在测试中创建的模拟未被使用。 Instead of creating instances of these objects in the constructor, you might consider passing them into the UserService constructor as arguments. 您可以考虑将它们作为参数传递给UserService构造函数,而不是在构造函数中创建这些对象的实例。 Then, you can pass in mocked instances in your test. 然后,您可以在测试中传入模拟实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM