简体   繁体   English

如何对包含数据库事务的代码进行单元测试

[英]How to unit test code that includes a database transaction

How to put unit around the below codes:如何将单位放在以下代码周围:

public DbContextTransaction QTTransactionBegin()
    {
        return Database.BeginTransaction();
    }

public int CreateCampaign(CreateCampaignModel createCampaignModel)
    {
        using (var transaction = _qtContext.QTTransactionBegin())
        {
            try
            {
                var campaign = new Campaign();
                campaign.CampaignCode = createCampaignModel.CampaignCode;
                campaign.CampaignDescription = createCampaignModel.CampaignDescription;
                campaign.CampaignDate = createCampaignModel.CampaignDate;
                campaign.CampaignNotes = createCampaignModel.CampaignNotes;
                campaign.OwnerUserID = createCampaignModel.OwnerUserID;
                campaign.AddedOn = DateTime.Now;
                campaign.AddedBy = createCampaignModel.OwnerUserName;
                campaign.UpdatedOn = DateTime.Now;
                campaign.UpdatedBy = createCampaignModel.OwnerUserName;
                campaign.CampaignSegments = GetCampaignSegmentList(createCampaignModel);

                var campaignId = AddOrUpdateCampaign(campaign);
                transaction.Commit();
                return campaignId;
            }
            catch (Exception ex)
            {
                transaction.Rollback();
            }
        }
        return 0;
    }

Could anyone advise me how to put unit test around above code ?谁能告诉我如何在上面的代码周围进行单元测试?

I tried the code as below :我尝试了如下代码:

Database_database;

    [TestInitialize]
    public void SetUp()
    {
        _qtDALMock = _factory.CreateMock<IQTDAL>();
        _campaignRepository = new CampaignRepository(_qtDALMock.MockObject);
    }
 [TestMethod]
    public void Check_CreateCampaign_Test()
    {
        // arrange 
        const int expectedCampaignId = 1;
        var createCampaign = QueryToolDummies.CreateCampaignModel;

        _database.BeginTransaction();
        _qtDALMock.Expects.One.MethodWith(x => x.QTTransactionBegin())
            .WillReturn(_database.BeginTransaction());
        _qtDALMock.Expects.One.Method(x => x.AddOrUpdateCampaign(null))
            .With(Is.TypeOf<Campaign>())
            .WillReturn(expectedCampaignId);

        // act
        var result = _campaignRepository.CreateCampaign(createCampaign);

        // assert
        Assert.IsNotNull(result);
    }

this _database.BeginTransaction() has a problem.这个_database.BeginTransaction()有问题。 the error says can't use like it.错误说不能像这样使用。

Please advise.请指教。

One question?一个问题? Why are you trying to start a transaction into a unit test?为什么要尝试将事务启动到单元测试中?

Will be easy if you Mock your repository using Moq framework and return what you need to return from the repo.如果您使用Moq framework模拟您的存储库并返回您需要从存储库返回的内容,那将会很容易。

In fact, I thought that start a BeginTransaction() in a unit test is not a good practice.事实上,我认为在单元测试中启动一个BeginTransaction()并不是一个好习惯。

I hope this helps我希望这有帮助

I've experienced the same issue, it's quite tricky to work around.我遇到了同样的问题,解决起来非常棘手。

I tried creating a wrapper class for the context that exposes a BeginTransaction() method, but ultimately you end up needing to mock the DbContextTransaction returned by BeginTransaction() when it comes to testing, but DbContextTransaction has neither an interface or a public constructor.我尝试为公开BeginTransaction()方法的上下文创建一个包装类,但最终您最终需要在测试时模拟BeginTransaction()返回的DbContextTransaction ,但DbContextTransaction既没有接口也没有公共构造函数。

In the end I wrote a transaction manager class that creates and manages its own transaction and exposes methods for beginning, committing and rolling back the transaction.最后我写了一个事务管理器类,它创建和管理自己的事务,并公开开始、提交和回滚事务的方法。 That manager class, and the service that returns it, can then be faked allowing the code using transactions to be fully tested.然后可以伪造该管理器类以及返回它的服务,从而允许对使用事务的代码进行全面测试。

I've written that up fully in this answer .我已经在这个答案中完整地写了。

You are trying to unit test more than one unit.您正在尝试对多个单元进行单元测试。

Assuming that the code above is your 'data layer' / repository then you are performing an integration test because more than a single unit is involved in the test.假设上面的代码是您的“数据层”/存储库,那么您正在执行集成测试,因为测试中涉及的单元不止一个。

You could include setup / teardown for the database within your test class and call the SUT (subject under test) with valid and invalid data to validate expected behaviours.您可以在测试类中包含数据库的设置/拆卸,并使用有效和无效数据调用 SUT(被测对象)以验证预期行为。

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

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