我知道日志记录是AOP的主要用例.此外,日志记录包装器也可以作为您希望使用DI的示例,以便类不与特定的日志记录实现相结合.但是,有些人认为日志包装器是一种反模式.首先,这样的视图是因为在大多数情况下,包装器往往是简单的并且删除了特定于日志框架的许多特征.如果您实现这些特定功能,为什么不直接使用框架.
我知道Common.Logging外观试图为您提取log4Net,EntLib,NLog的大量功能.但是,即使在这里,我们仍然依赖于Common.Logging.不是关于接口等的代码/单元测试方式,但如果项目死亡(自上次发布以来已超过一年)或者您希望后者切换到不支持的记录器,则可能导致问题.
也就是说,如果通过AOP实现日志记录,是否有必要使用DI作为日志记录依赖项(即为什么不直接引用说NLog)?是的,AOP部分代码将紧密耦合,但是想要进行单元测试的类的逻辑缺乏记录依赖性(至少在编织发生之前).在这一点上,我有点迷失(我还没有尝试过AOP).编织后,没有使用DI作为AOP代码会导致单元测试被测方法的问题吗?或者可以在不编织AOP代码的情况下测试一个单元吗?
除非日志记录是软件用户的要求,否则我不确定测试日志是否与模拟有关是多么有用.我认为被测方法的业务逻辑是大多数人对测试感兴趣的东西.最后,如果想要使用TDD/BDD,是否必须在AOP代码中使用DI来记录日志依赖?或者只是不测试驱动 AOP方面的东西?
正如您所看到的,我正在尝试了解最实用的方法是开发一个应用程序,该应用程序将AOP用于横切关注点,DI用于设计/测试.由于AOP相对较新,而日志记录是最常见的例子,推荐的方法是什么?
我正在寻找在整个交易中使用当前日期和时间的一致值的指导原则.
通过事务我松散地表示应用程序服务方法,这种方法通常执行单个SQL事务,至少在我的应用程序中.
在这个问题的答案中描述的一种方法是将当前日期放在环境上下文中,例如DateTimeProvider,并使用它来代替DateTime.UtcNow任何地方.
然而,这种方法的目的只是为了使设计单元可测试,而我还想防止由不必要的多次查询引起的错误DateTime.UtcNow,其中一个例子如下:
// In an entity constructor:
this.CreatedAt = DateTime.UtcNow;
this.ModifiedAt = DateTime.UtcNow;
Run Code Online (Sandbox Code Playgroud)
此代码创建的实体具有稍微不同的创建和修改日期,而人们希望这些属性在创建实体后立即相等.
此外,环境上下文很难在Web应用程序中正确实现,所以我想出了另一种方法:
DeterministicTimeProvider类被登记为"每寿命实例范围" AKA依赖性"每HTTP请求在网络应用程序的实例".IDateTimeProvider.UtcNow方法代替通常DateTime.UtcNow/ DateTimeOffset.UtcNow到处获取当前日期和时间.这是实施:
/// <summary>
/// Provides the current date and time.
/// The provided value is fixed when it is requested for the first time.
/// </summary>
public class DeterministicTimeProvider: IDateTimeProvider
{
private readonly Lazy<DateTimeOffset> _lazyUtcNow =
new Lazy<DateTimeOffset>(() => DateTimeOffset.UtcNow); …Run Code Online (Sandbox Code Playgroud) 我正在寻找Microsoft Fakes in .NET Core的替代方案.我知道.NET Core不再支持它.我只是不明白为什么不,我认为这在某些情况下是一个很好的解决方案.
我的问题是我想模拟DateTime.Now.以前您可以使用以下代码执行此操作:
System.Fakes.ShimDateTime.NowGet = () =>
{
return new DateTime(2000, 1, 1);
};
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅Microsoft文档中的链接:https://docs.microsoft.com/en-us/visualstudio/test/using-shims-to-isolate-your-application-from-other-assemblies -用于单元测试?视图= VS-2017
现在我通过为DateTime创建一个包装器来解决它,如下所示:
/// <summary>
/// Used for getting DateTime.Now(), time is changeable for unit testing
/// </summary>
public static class SystemTime
{
/// <summary>
/// Normally this is a pass-through to DateTime.Now, but it can be
/// overridden with SetDateTime( .. ) for testing or debugging.
/// </summary>
public static Func<DateTime> Now = () => DateTime.Now;
/// …Run Code Online (Sandbox Code Playgroud) 我有这种方法取决于当前日期.它检查今天是太阳,周一,周二还是周三,然后它给出了5天的交货时间.如果它是星期四,星期五或星期六那么它给出了6天的交货时间来解释周末.
private DateTime GetEstimatedArrivalDate()
{
DateTime estimatedDate;
if (DateTime.Now.DayOfWeek >= DayOfWeek.Thursday)
{
estimatedDate = DateTime.Now.Date.AddDays(6);
}
else
{
estimatedDate = DateTime.Now.Date.AddDays(5);
}
return estimatedDate;
}
Run Code Online (Sandbox Code Playgroud)
实际的估算逻辑更复杂.为了这个问题,我简化了它.我的问题是如何根据今天的日期为这样的事情编写单元测试?
我已经使用 ASP.NET Identity 2.2.1 成功构建了简单的注册系统。
我只需要 API,所以我构建了允许使用 route 创建帐户的简单控制器account/create,当创建帐户时,用户会收到带有确认电话所需的令牌的 SMS 消息,同时我生成验证电子邮件地址所需的链接,我正在将其发送到用户电子邮件地址。然后用户需要从 SMS 输入令牌(向 请求account/confirm_phone)并单击他收到的电子邮件中的链接。
激活账户需要这两个操作,这部分工作正常。
我需要将电子邮件链接更改为电子邮件令牌,类似于用于确认电话号码的令牌,因此用户不必单击链接,而是必须输入该令牌(请求到account/confirm_email)
方法GenerateEmailConfirmationTokenAsync返回很长的代码,成为电子邮件中发送的链接的一部分,我希望它返回 6 位令牌。
我无法重用,GeneratePhoneConfirmationTokenAsync因为这将生成与通过 SMS 发送相同的令牌。
我在互联网上搜索过,但找不到任何关于如何自定义GenerateEmailConfirmationTokenAsync方法生成的令牌的信息。
是否可以配置该令牌生成器,以便它返回 6(或任何可配置长度)数字代码,我可以用它来确认用户电子邮件地址。
我知道将链接发送给用户是更好的选择,但正如我写的那样,这是我得到的要求,我无法改变它。
我使用VS2008目标.NET 2.0框架,以防万一,不,我不能改变这个:)
我DateCalculator上课了.其方法GetNextExpirationDate尝试在内部使用DateTime.Today作为基线日期来确定下一个到期时间.
在我编写单元测试时,我意识到我想测试GetNextExpirationDate不同的"今天"日期.
最好的方法是什么?以下是我考虑过的一些替代方案:
baselineDate仅在单元测试中使用它.在实际的客户端代码,忽略了赞成票默认方法的属性/重载方法baselineDate来DateTime.Today.我不愿意这样做,因为它使得DateCalculator类的公共接口变得笨拙.baselineDate内部设置为的受保护字段DateTime.Today.测试时,DateCalculatorForTesting从构造函数派生DateCalculator并设置baslineDate.它使公共接口保持干净,但仍然不是很好 - baselineDate受到保护并且需要派生类,这两者都仅用于测试.ExtensionAttribute,然后意识到它不起作用,因为扩展方法无法访问私有/受保护的变量.我最初认为这是一个非常优雅的解决方案.:(我有兴趣听听别人的想法.
您将如何测试与时间相关的方法?
一个简单的例子可能是:
public static int GetAge(DateTime birthdate)
{
// ...
}
[TestMethod]
public void GetAgeTest()
{
// This is only ok for year 2013 !
Assert.AreEqual(GetAge(new DateTime(2000, 1, 1)), 13);
}
Run Code Online (Sandbox Code Playgroud)
问题是它仅适用于当前年份(在本例中为 2013)。新的一年一开始,我就必须重写所有与时间相关的测试......
单元测试这种方法的最佳方法是什么?
这是贫血领域模型:
public partial class Person
{
public virtual int PersonId { get; internal protected set; }
public virtual string Title { get; internal protected set; }
public virtual string FirstName { get; internal protected set; }
public virtual string MiddleName { get; internal protected set; }
public virtual string LastName { get; internal protected set; }
}
Run Code Online (Sandbox Code Playgroud)
这是它的行为:
public static class Services
{
public static void UpdatePerson(Person p, string firstName, string lastName)
{
// validate firstname and lastname
// …Run Code Online (Sandbox Code Playgroud) 我在C#中创建了一个应用程序,我想在特定时间测试这个应用程序Day,Week,Year是否有任何空闲时间模拟软件可以做到这一点或任何其他方式?
c# ×7
unit-testing ×5
datetime ×3
.net ×2
.net-core ×1
aop ×1
asp.net ×1
logging ×1
moq ×1
time ×1
transactions ×1
web-services ×1