我一直在使用moq来模拟单元测试中的对象,我在网站上看到moq它能够模拟类和接口.
前几天我与我的一个工作伙伴进行了讨论,他们表示没有理由去模拟课程,我只应该模拟界面.
我没有真正得到答案......我似乎也无法在moq网站上找到任何答案.
一个人永远不应该嘲笑课程是真的吗?我会说不,因为如果那是真的,那么Moq甚至不会允许它......那么有时候在界面上模拟一个类更好吗?模拟类与模拟接口有什么区别?或者它真的只是一个偏好的东西?
我有一个工作单元实施,其中包括以下方法:
T Single<T>(Expression<Func<T, bool>> expression) where T : class, new();
Run Code Online (Sandbox Code Playgroud)
我打电话给它,例如,像这样:
var person = _uow.Single<Person>(p => p.FirstName == "Sergi");
Run Code Online (Sandbox Code Playgroud)
如何验证Single方法是否已使用参数调用FirstName == "Sergi"?
我试过以下,但无济于事:
// direct approach
session.Verify(x => x.Single<Person>(p => p.FirstName == "Sergi"));
// comparing expressions
Expression<Func<Person, bool>> expression = p => p.FirstName == "Sergi");
session.Verify(x => x
.Single(It.Is<Expression<Func<Person, bool>>>(e => e == expression));
Run Code Online (Sandbox Code Playgroud)
它们都会导致以下错误:
模拟上的预期调用至少一次,但从未执行过
关于如何做到这一点的任何想法?我正在使用NuGet 的最新Moq,版本4.0.10827.0
更新:一个具体的例子
我所看到的是每当我在lambda中使用字符串文字时,都Verify可以工作.一旦我比较变量就失败了.例证:
// the verify
someService.GetFromType(QuestionnaireType.Objective)
session.Verify(x => x.Single<Questionnaire>(q =>
q.Type == QuestionnaireType.Objective));
// …Run Code Online (Sandbox Code Playgroud) 我正在尝试学习如何使用C#和Moq进行单元测试,并且我已经构建了一个小测试情况.鉴于此代码:
public interface IUser
{
int CalculateAge();
DateTime DateOfBirth { get; set; }
string Name { get; set; }
}
public class User : IUser
{
public DateTime DateOfBirth { get; set; }
string Name { get; set; }
public int CalculateAge()
{
return DateTime.Now.Year - DateOfBirth.Year;
}
}
Run Code Online (Sandbox Code Playgroud)
我想测试一下这个方法CalculateAge().为此,我想我应该尝试DateOfBirth通过在我的测试方法中执行此操作来为属性提供默认值:
var userMock = new Mock<IUser>();
userMock.SetupProperty(u => u.DateOfBirth, new DateTime(1990, 3, 25)); //Is this supposed to give a default value for the property DateOfBirth ?
Assert.AreEqual(22, …Run Code Online (Sandbox Code Playgroud) 我正在财务系统中实施单元测试,涉及多个计算.其中一个方法是通过参数接收具有100个以上属性的对象,并根据此对象的属性计算返回值.为了实现此方法的单元测试,我需要让所有这个对象都填充有效值.
所以......问题:今天这个对象是通过数据库填充的.在我的单元测试中(我正在使用NUnit),我需要避开数据库并创建一个模拟对象,以仅测试方法的返回.如何用这个巨大的对象有效地测试这个方法?我真的需要手动填写它的所有100个属性吗?有没有办法使用Moq自动化这个对象创建(例如)?
obs:我正在为已经创建的系统编写单元测试.目前重写所有架构是不可行的.
太感谢了!
我正在尝试创建一个模拟(使用Moq),IServiceProvider以便我可以测试我的存储库类:
public class ApiResourceRepository : IApiResourceRepository
{
private readonly IServiceProvider _serviceProvider;
public ApiResourceRepository(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
_dbSettings = dbSettings;
}
public async Task<ApiResource> Get(int id)
{
ApiResource result;
using (var serviceScope = _serviceProvider.
GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
result = await
context.ApiResources
.Include(x => x.Scopes)
.Include(x => x.UserClaims)
.FirstOrDefaultAsync(x => x.Id == id);
}
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
我创建Mock对象的尝试如下:
Mock<IServiceProvider> serviceProvider = new Mock<IServiceProvider>();
serviceProvider.Setup(x => x.GetRequiredService<ConfigurationDbContext>())
.Returns(new ConfigurationDbContext(Options, StoreOptions));
Mock<IServiceScope> serviceScope = new Mock<IServiceScope>(); …Run Code Online (Sandbox Code Playgroud) 从新的CosmosDb模拟器我得到了一个存储库来执行基本的documentdb操作,这个存储库被注入其他类.我想对基本查询进行单元测试.
public class DocumentDBRepository<T> where T : class
{
//Details ommited...
public IQueryable<T> GetQueryable()
{
return _client.CreateDocumentQuery<T>(
UriFactory.CreateDocumentCollectionUri(_databaseId, _collectionId),
new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true });
}
public async Task<IEnumerable<T>> ExecuteQueryAsync(IQueryable<T> query)
{
IDocumentQuery<T> documentQuery = query.AsDocumentQuery();
List<T> results = new List<T>();
while (documentQuery.HasMoreResults)
{
results.AddRange(await documentQuery.ExecuteNextAsync<T>());
}
return results;
}
}
Run Code Online (Sandbox Code Playgroud)
此存储库需要一个文档客户端才能工作,它也会在构造函数上注入.
public DocumentDBRepository(string databaseId, IDocumentClient client)
{
_client = client;
_databaseId = databaseId;
_collectionId = GetCollectionName();
}
Run Code Online (Sandbox Code Playgroud)
我最初的方法是使用CosmosDb模拟器,但这需要模拟器运行我不喜欢并使测试更慢.
我的第二种方法是尝试使用文档客户端的模拟.
var data = new List<MyDocumentClass>
{ …Run Code Online (Sandbox Code Playgroud) 我正在使用 ASP.NET Core 2.2、EF Core 和 MOQ。正如您在以下代码中所看到的,我有两个测试,并且同时运行,两个数据库名称均为“MovieListDatabase” 我在其中一个测试中出现错误并显示此消息:
Message: System.ArgumentException : An item with the same key has already
been added. Key: 1
Run Code Online (Sandbox Code Playgroud)
如果我分别运行每一个,它们都会通过。
而且,在两个测试中使用不同的数据库名称,例如“MovieListDatabase1”和“MovieListDatabase2”并且同时运行它再次通过。
我有两个问题:为什么会发生这种情况?以及如何重构我的代码以在两个测试中重用内存数据库并使我的测试看起来更简洁?
public class MovieRepositoryTest
{
[Fact]
public void GetAll_WhenCalled_ReturnsAllItems()
{
var options = new DbContextOptionsBuilder<MovieDbContext>()
.UseInMemoryDatabase(databaseName: "MovieListDatabase")
.Options;
// Insert seed data into the database using one instance of the context
using (var context = new MovieDbContext(options))
{
context.Movies.Add(new Movie { Id = 1, Title = "Movie 1", YearOfRelease = 2018, Genre = "Action" }); …Run Code Online (Sandbox Code Playgroud) 我是Moq的新手并且正在学习.
我需要测试一个方法返回预期的值.我已经整理了一个例子来解释我的问题.这失败了:
"ArgumentException:Expression不是方法调用:c =>(c.DoSomething("Jo","Blog",1)="OK")"
你能纠正我做错的事吗?
[TestFixtureAttribute, CategoryAttribute("Customer")]
public class Can_test_a_customer
{
[TestAttribute]
public void Can_do_something()
{
var customerMock = new Mock<ICustomer>();
customerMock.Setup(c => c.DoSomething("Jo", "Blog", 1)).Returns("OK");
customerMock.Verify(c => c.DoSomething("Jo", "Blog", 1)=="OK");
}
}
public interface ICustomer
{
string DoSomething(string name, string surname, int age);
}
public class Customer : ICustomer
{
public string DoSomething(string name, string surname, int age)
{
return "OK";
}
}
Run Code Online (Sandbox Code Playgroud)
简而言之:如果我想测试一个像上面那样的方法,并且我知道我期待回到"OK",我将如何使用Moq编写它?
谢谢你的任何建议.
我使用过编写过NUnit测试的代码.但是,我从未使用过模拟框架.这些是什么?我理解依赖注入以及它如何帮助提高可测试性.我的意思是所有依赖项都可以在单元测试时进行模拟.但是,为什么我们需要模拟框架呢?我们不能简单地创建模拟对象并提供依赖关系.我在这里错过了什么吗?谢谢.
我有这样的界面:
public interface IMyInterface
{
event EventHandler<bool> Triggered;
void Trigger();
}
Run Code Online (Sandbox Code Playgroud)
我在我的单元测试中有一个模拟对象,如下所示:
private Mock<IMyInterface> _mockedObject = new Mock<IMyInterface>();
Run Code Online (Sandbox Code Playgroud)
我想做这样的事情:
// pseudo-code
_mockedObject.Setup(i => i.Trigger()).Raise(i => i.Triggered += null, this, true);
Run Code Online (Sandbox Code Playgroud)
但是,在返回Raise的ISetup接口上看起来不可用.我该怎么做呢?