标签: moq

如何使用Entity Framework Core模拟异步存储库

我正在尝试为调用异步存储库的类创建单元测试.我正在使用ASP.NET Core和Entity Framework Core.我的通用存储库看起来像这样.

public class EntityRepository<TEntity> : IEntityRepository<TEntity> where TEntity : class
{
    private readonly SaasDispatcherDbContext _dbContext;
    private readonly DbSet<TEntity> _dbSet;

    public EntityRepository(SaasDispatcherDbContext dbContext)
    {
        _dbContext = dbContext;
        _dbSet = dbContext.Set<TEntity>();
    }

    public virtual IQueryable<TEntity> GetAll()
    {
        return _dbSet;
    }

    public virtual async Task<TEntity> FindByIdAsync(int id)
    {
        return await _dbSet.FindAsync(id);
    }

    public virtual IQueryable<TEntity> FindBy(Expression<Func<TEntity, bool>> predicate)
    {
        return _dbSet.Where(predicate);
    }

    public virtual void Add(TEntity entity)
    {
        _dbSet.Add(entity);
    }
    public virtual void Delete(TEntity entity)
    {
        _dbSet.Remove(entity);
    }

    public virtual …
Run Code Online (Sandbox Code Playgroud)

c# unit-testing moq entity-framework-core asp.net-core

61
推荐指数
4
解决办法
2万
查看次数

表达式<Func <T,bool >>的Moq'ing方法作为参数传入

我对单元测试和嘲笑很新!我正在尝试编写一些单元测试,其中包含一些与数据存储交互的代码.数据访问由IRepository封装:

interface IRepository<T> {
    ....
    IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate);
    ....
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用具体的IoC实现的IRepository来测试的代码如下所示:

public class SignupLogic {
    private Repository<Company> repo = new Repository<Company>();

    public void AddNewCompany(Company toAdd) {
        Company existingCompany = this.repo.FindBy(c => c.Name == toAdd.Name).FirstOrDefault();

        if(existingCompany != null) {
            throw new ArgumentException("Company already exists");
        }

        repo.Add(Company);
        repo.Save();
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,我正在测试SignupLogic.AddNewCompany()本身的逻辑,而不是逻辑和具体的存储库,我正在模拟IRepository并将其传递给SignupLogic.模拟的存储库看起来像这样:

Mock<Repository> repoMock = new Mock<Repository>();
repoMock.Setup(moq => moq.FindBy(c => c.Name == "Company Inc")....
Run Code Online (Sandbox Code Playgroud)

它返回一个内存中的IEnumberable,其中包含名称设置为"Company Inc"的Company对象.调用SignupLogic.AddNewCompany的单元测试会设置一个具有重复详细信息和trys的公司来传递它,并且我断言抛出了ArgumentException,并显示消息"公司已存在".这个测试没有通过.

在运行时通过单元测试和AddNewCompany()进行调试,似乎existingCompany始终为null.无奈之下,我发现如果我更新SignupLogic.AddNewCompany()以便对FindBy的调用如下所示:

Company existingCompany = this.repo.FindBy(c => c.Name == "Company Inc").FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

测试通过,这告诉我,Moq只响应与我在测试夹具中设置的代码完全相同的代码.显然,在测试任何重复的公司被SignupLogic.AddNewCompany拒绝时,这并不是特别有用.

我已经尝试设置moq.FindBy(...)来使用"Is.ItAny",但这并不会导致测试通过.

从我正在阅读的所有内容来看,似乎我正在尝试测试表达式实际上并不能在这里使用Moq.可能吗?请帮忙!

c# unit-testing moq

60
推荐指数
2
解决办法
3万
查看次数

SetupSet()已过时.代替什么?

假设我想使用Moq在setter上创建一个回调,以便将set属性存储在我自己的字段中供以后使用.(有争议的例子 - 但问题就到了.)我可以这样做:

myMock.SetupSet(x => x.MyProperty).Callback(value => myLocalVariable = value);
Run Code Online (Sandbox Code Playgroud)

这很好用.但是,根据Intellisense,SetupSet已经过时了.但它没有说应该用什么作为替代品.我知道moq提供了SetupProperty,它将使用支持字段自动装配该属性.但这不是我想要的.我想将设定值捕获到我自己的变量中.我应该如何使用非过时的方法?

.net c# unit-testing moq mocking

59
推荐指数
1
解决办法
2万
查看次数

在Moq中重置模拟验证?

设置如下:

public interface IFoo
{
    void Fizz();
}

[Test]
public void A()
{
    var foo = new Mock<IFoo>(MockBehavior.Loose);

    foo.Object.Fizz();

    foo.Verify(x => x.Fizz());

    // stuff here

    foo.Verify(x => x.Fizz(), Times.Never()); // currently this fails
}
Run Code Online (Sandbox Code Playgroud)

基本上我想// stuff herefoo.Verify(x => x.Fizz(), Times.Never())传递中输入一些代码.

因为这可能构成moq/unit测试滥用,我的理由是我可以这样做:

[Test]
public void Justification()
{
    var foo = new Mock<IFoo>(MockBehavior.Loose);
    foo.Setup(x => x.Fizz());

    var objectUnderTest = new ObjectUnderTest(foo.Object);

    objectUnderTest.DoStuffToPushIntoState1(); // this is various lines of code and setup

    foo.Verify(x => x.Fizz());

    // reset the verification …
Run Code Online (Sandbox Code Playgroud)

c# unit-testing moq

58
推荐指数
4
解决办法
3万
查看次数

将Moq模拟对象传递给构造函数

我一直在使用RhinoMocks,但刚开始研究Moq.我有这个非常基本的问题,令我感到惊讶的是,这并不是开箱即用的.假设我有以下类定义:

public class Foo
{
    private IBar _bar; 
    public Foo(IBar bar)
    {
        _bar = bar; 
    }
    ..
}
Run Code Online (Sandbox Code Playgroud)

现在我有一个测试,我需要模拟发送到Foo的IBar.在RhinoMocks中,我会像下面这样做,它会很有效:

var mock = MockRepository.GenerateMock<IBar>(); 
var foo = new Foo(mock); 
Run Code Online (Sandbox Code Playgroud)

但是,在Moq中,这似乎并没有以同样的方式起作用.我这样做:

var mock = new Mock<IBar>(); 
var foo = new Foo(mock); 
Run Code Online (Sandbox Code Playgroud)

然而,现在它失败了 - 告诉我"无法从'Moq.Mock'转换为'IBar'.我做错了什么?用Moq做这个的推荐方法是什么?

.net c# moq mocking

56
推荐指数
2
解决办法
2万
查看次数

Setup()vs SetupGet()

MOQ的SetupGet()和Setup()方法有什么区别?

moq

55
推荐指数
2
解决办法
2万
查看次数

使用Moq验证呼叫是否按正确的顺序进行

我需要测试以下方法:

CreateOutput(IWriter writer)
{
    writer.Write(type);
    writer.Write(id);
    writer.Write(sender);

    // many more Write()s...
}
Run Code Online (Sandbox Code Playgroud)

我创建了一个Moq'd IWriter,我想确保Write()以正确的顺序调用这些方法.

我有以下测试代码:

var mockWriter = new Mock<IWriter>(MockBehavior.Strict);
var sequence = new MockSequence();
mockWriter.InSequence(sequence).Setup(x => x.Write(expectedType));
mockWriter.InSequence(sequence).Setup(x => x.Write(expectedId));
mockWriter.InSequence(sequence).Setup(x => x.Write(expectedSender));
Run Code Online (Sandbox Code Playgroud)

但是,第二次调用Write()in CreateOutput()(写入id值)会抛出一条MockException消息" IWriter.Write()调用失败,模拟行为为Strict.模拟上的所有调用都必须有相应的设置. "

我也发现很难找到任何明确的,最新的Moq序列文档/示例.

我做错了什么,或者我不能使用相同的方法设置序列?如果没有,有没有我可以使用的替代品(最好使用Moq/NUnit)?

c# nunit unit-testing moq sequential

55
推荐指数
6
解决办法
2万
查看次数

MOQ文件在哪里?

我在哪里可以找到MOQ的综合文档?我只是从嘲笑开始,我很难理解它.我已经阅读了http://code.google.com/p/moq/wiki/QuickStart上的所有链接,但似乎无法找到教程或温和的介绍.

我还简要介绍了Rhino Mocks,但发现它非常令人困惑.


是的 - 我读过Stephen Walthers的文章 - 非常有帮助.我也通过了链接.我似乎无法在http://www.bestechvideos.com/2008/06/08/dimecasts-net-introduction-to-mocking-with-moq 观看视频[断链]

具体来说,我试图确定是否从模拟类中引发了一个事件.我无法获得QuickStarts页面上的事件编译示例.在google组中,Daniel解释说CreateEventHandler只能处理类型的事件EventHandler<TEventArgs>,但即使这样我也无法获得编译代码.

更具体地说,我有一个实现的类INotifyChanged.

public class Entity : INotifyChanged
{
    public event PropertyChangingEventHandler PropertyChanging;

    public int Id 
      { 
          get {return _id;}
          set {
                 _id = value;
                 OnPropertyChanged("Id");
              }
      }

     protected void OnPropertyChanged(string property)
      {
         if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
      }
 etc .....    
}
Run Code Online (Sandbox Code Playgroud)

如何模拟该类以测试PropertyChanged事件是否被触发?我不能重写事件,public event EventHandler<PropertyChangedEventArgs>因为我得到这个错误:

错误1'CoreServices.Notifier'未实现接口成员System.ComponentModel.INotifyPropertyChanged.PropertyChanged'.'CoreServices.Notifier.PropertyChanged'无法实现'System.ComponentModel.INotifyPropertyChanged.PropertyChanged',因为它没有匹配的返回类型'System.ComponentModel.PropertyChangedEventHandler'.

.net c# testing moq mocking

54
推荐指数
3
解决办法
4万
查看次数

模拟一个抛出异常(moq)的方法,但其他方式就像模拟对象一样?

我有一个Transfer类,简化它看起来像这样:

public class Transfer
{
    public virtual IFileConnection source { get; set; }
    public virtual IFileConnection destination { get; set; }

    public virtual void GetFile(IFileConnection connection, 
        string remoteFilename, string localFilename)
    {
        connection.Get(remoteFilename, localFilename);
    }

    public virtual void PutFile(IFileConnection connection, 
        string localFilename, string remoteFilename)
    {
        connection.Get(remoteFilename, localFilename);
    }

    public virtual void TransferFiles(string sourceName, string destName)
    {
        source = internalConfig.GetFileConnection("source");
        destination = internalConfig.GetFileConnection("destination");
        var tempName = Path.GetTempFileName();
        GetFile(source, sourceName, tempName);
        PutFile(destination, tempName, destName);
    }
}
Run Code Online (Sandbox Code Playgroud)

IFileConnection界面的简化版本如下所示:

public interface IFileConnection …
Run Code Online (Sandbox Code Playgroud)

c# unit-testing moq mocking

54
推荐指数
3
解决办法
8万
查看次数

Moq中的SetupSequence

我想模拟第一次返回0,然后在调用方法的任何时候返回1.问题是,如果方法被调用4次,我应该写:

mock.SetupSequence(x => x.GetNumber())
    .Returns(0)
    .Returns(1)
    .Returns(1)
    .Returns(1);
Run Code Online (Sandbox Code Playgroud)

否则该方法返回null.

有没有办法写下次在第一次调用该方法后,该方法返回1?谢谢

为SetupSequence设置更多"运营商"是否合适?如果您认为是,您可以投票:http: //moq.uservoice.com/forums/11304-general/suggestions/2973521-setupsequence-more-operators

c# unit-testing moq mocking

54
推荐指数
6
解决办法
2万
查看次数