我想使用Autofixture创建FormsAuthenticationTicket的实例(我无法控制,部分是System.Web.Security)并确保UserData(类型为string)包含有效的XML字符串
var testTicket = fixture.Create<FormsAuthenticationTicket>();
问题是UserData只能在使用以下构造函数实例化对象时设置:
public FormsAuthenticationTicket(int version, string name, DateTime issueDate, DateTime expiration, bool isPersistent, string userData);
其中&#34; userData&#34;是一个有效的XML字符串。
我可以将此类型配置为使用最贪婪的构造函数,但这并不能解决向userData提供有效XML字符串的问题。
我可以冻结字符串类型以使其始终返回有效的XML字符串,但我也关心我的测试中的其他字符串值。
我在想一种可能的方法是自定义字符串生成算法......但是我没有参数来知道何时提供类似字符串的XML。
答案 0 :(得分:2)
冻结字符串会起作用,但是不可取,因为它也会影响所有其他生成的字符串。
我使用此类来自定义特定的构造函数参数:
public class GenericArgCustomization<T> : ISpecimenBuilder
{
private readonly string name;
private readonly T value;
public GenericArgCustomization(string name, T value)
{
if (String.IsNullOrEmpty(name))
throw new ArgumentException("Name is required", "name");
this.name = name;
this.value = value;
}
public object Create(object request, ISpecimenContext context)
{
var pi = request as ParameterInfo;
if (pi == null)
return new NoSpecimen(request);
if (pi.ParameterType != typeof(T) || pi.Name != this.name)
return new NoSpecimen(request);
return this.value;
}
}
接下来,您可以通过指定泛型类型(在本例中为string
)和要自定义的构造函数参数名称(在本例中为userData
)来使用它。这是区分大小写的,因此它匹配您在类中使用的参数名称。
示例:
var xml = "<root>My Valid XML Value Here</root>";
var customUserData = new GenericArgCustomization<string>("userData", xml);
var fixture = new Fixture();
fixture.Customizations.Add(customUserData);
var item = fixture.Create<FormsAuthenticationTicket>();
现在使用以下数据创建项目:
85
name1e8fb8b1-5879-4256-8729-ca6afeb1bd80
12/3/2015 8:00:05 AM
True
<root>My Valid XML Value Here</root>
答案 1 :(得分:2)
AutoFixture选择适度的构造函数(默认情况下),因为userData
不是适度的构造函数的一部分,我们需要在这里自定义两个的东西:
userData
构造函数参数提供自定义值。以下自定义包含两者:
internal class UserDataCustomization : ICustomization
{
private readonly string userData;
public UserDataCustomization(string userData)
{
this.userData = userData;
}
public void Customize(IFixture fixture)
{
fixture.Customize<FormsAuthenticationTicket>(c =>
c.FromFactory(
new MethodInvoker(
new GreedyConstructorQuery())));
fixture.Customizations.Add(new UserDataBuilder(this.userData));
}
private class UserDataBuilder : ISpecimenBuilder
{
private readonly string userData;
public UserDataBuilder(string userData)
{
this.userData = userData;
}
public object Create(object request, ISpecimenContext context)
{
var pi = request as ParameterInfo;
if (pi != null && pi.Name == "userData")
return this.userData;
return new NoSpecimen();
}
}
}
以下测试通过:
[Fact]
public void UserDataIsCorrect()
{
var expected = "<foo></foo>";
var fixture = new Fixture();
fixture.Customize(new UserDataCustomization(expected));
var actual = fixture.Create<FormsAuthenticationTicket>();
Assert.Equal(expected, actual.UserData);
}
希望有所帮助。
FWIW,F#中也是如此:
open Ploeh.AutoFixture
open Ploeh.AutoFixture.Kernel
open System
open System.Reflection
open System.Web.Security
type UserDataCustomization (userData) =
let builder = {
new ISpecimenBuilder with
member this.Create(request, context) =
match request with
| :? ParameterInfo as pi
when pi.Name = "userData" -> box userData
| _ -> NoSpecimen request |> box }
interface ICustomization with
member this.Customize fixture =
fixture.Customize<FormsAuthenticationTicket>(fun c ->
c.FromFactory(
MethodInvoker(
GreedyConstructorQuery())) :> ISpecimenBuilder)
fixture.Customizations.Add builder
以下测试通过:
open Xunit
open Swensen.Unquote.Assertions
[<Fact>]
let UserDataIsCorrect () =
let expected = "<foo></foo>"
let fixture = Fixture().Customize(UserDataCustomization(expected))
let actual = fixture.Create<FormsAuthenticationTicket>()
test <@ expected = actual.UserData @>