如何在不保存到数据库的情况下对SaveInfo方法进行单元测试

时间:2012-10-25 22:10:42

标签: c# unit-testing

这是我的班级:

public class AuditInfo
{
    public String ActionDescription { get; set; }
    public String ActionWho { get; set; }
    public BasicProjectProfile Project { get; set; }


    public AuditInfo ()
    { }

    public void SaveInfo ()
    {
        using (CIHEntities _dbContext = new CIHEntities())
        {
            AuditInfoEntity aie = new AuditInfoEntity();
            aie.ActionDescription = this.ActionDescription;
            aie.ActionWhen = DateTime.Now;
            if (this.ActionWho != null)
            {
                aie.ActionWho = this.ActionWho;
            }
            else
            {
                aie.ActionWho = "Not Specified";
            }
            aie.ProjectAssoc = _dbContext.ProjectEntity
                .Where(r => r.Id == this.Project.Id)
                .First();
            _dbContext.SaveChanges();
        }
    }
}

CIHEntities是一个实体框架数据库。

我想对SaveInfo方法进行单元测试,但实际上不应该保存到数据库中。怎么能这样做?

由于

埃里克

3 个答案:

答案 0 :(得分:0)

Given : that Id don't know what is the interface of CIHEntities
When : Unit Test is required for AuditInfo.SaveInfo
Then : inject the interface of CIHEntities from constructor of AuditInfo
Then : create a mock of CIHEntities from its interface and use it for Unit Test

请模仿期望并验证使用模拟库(例如Moq

)调用SaveChanges

答案 1 :(得分:0)

使用Repository模式并将保存enity的责任转移到Repository:

public class AuditInfo
{
    public String ActionDescription { get; set; }
    public String ActionWho { get; set; }
    public BasicProjectProfile Project { get; set; }
}

为您的存储库编写一个接口:

public interface IRepository
{
    void Save();
}

然后你的实施:

public RealRepository : IRepository
{
    public void SaveInfo ()
    {
        using (CIHEntities _dbContext = new CIHEntities())
        {
            AuditInfoEntity aie = new AuditInfoEntity();
            aie.ActionDescription = this.ActionDescription;
            aie.ActionWhen = DateTime.Now;
            if (this.ActionWho != null)
            {
                aie.ActionWho = this.ActionWho;
            }
            else
            {
                aie.ActionWho = "Not Specified";
            }
            aie.ProjectAssoc = _dbContext.ProjectEntity
                .Where(r => r.Id == this.Project.Id)
                .First();
            _dbContext.SaveChanges();
        }
    }
}

然后使您的客户端代码将存储库作为参数将是这样的

public class MyClient{

    IRepository _repository;

    public MyClient(){
        _repository = new RealRepository();
    }

    public MyClient(IRepository repository)
    {
        _repository = repository;
    }

    public void Main(){
         AuditInfo entity = new AuditInfo();
         //do whatever you want
         _repository.Save();
    }
}

您的真实应用程序可以使用默认构造函数,它将使用RealRepository,而单元测试可以传递一个不与数据库对话的Fake Repository实现(或者甚至更好地使用像Moq这样的Mocking框架)。

这是基本概念,您可以改进它以拥有通用存储库,使用UoW模式...您可以在这篇msdn文章中阅读更多相关信息:Testability and EF

答案 2 :(得分:0)

使用TransactionScope。除非您实际提交更改,否则不会将其添加到数据库中。这就是我在单元测试中使用的,它完美无缺。

要使用它,您必须添加对System.Transactions的引用,之后您可能会收到一些Windows错误。如果我没记错的话,你必须启动一些Windows服务。但是,当你走得那么远的时候谷歌吧。