在使用XUnit编写某些单元之前,我碰到了一些令人惊讶的事情:
let id = Guid.Empty
let contact = {
Name = {
FirstName = "Marcel"
MiddleInitial = None
LastName = "Patulacci"
}
DateOfBith = new DateTime(1850, 12, 25)
Address = {
Address1 = "41 av 8 Mai 1945"
Address2 = None
City = "Sarcelles"
State = None
Zip = "95200"
}
PhoneNumber = {
DialOutCode = 33
LocalNumber = "766030703"
}
Email = "marcel.patulacci@outlook.com"
}
[<Fact>]
let ``Open an account...``() =
let event = Event.AccountOpened({
AccountId = id
Contact = contact
})
let a = [event]
let b = seq { yield event }
Assert.Equal(a, b)
System.NullReferenceException
:对象引用未设置为对象的实例。
尤其令人惊奇的是,考虑到Assert
使用的重载为:
public static void Equal<T>(IEnumerable<T> expected, IEnumerable<T> actual)
其中指出:
使用默认比较器验证两个序列是否相等。
为什么他们被认为与众不同,为什么Assert.Equal
提出System.NullReferenceException
?
[编辑]
System.NullReferenceException
:未将对象引用设置为对象的实例。 在Domain.Events.AccountOpenedEvent.Equals(Object obj, IEqualityComparer comp)
在Domain.Events.Event.Equals(Object obj, IEqualityComparer comp)
似乎
type PersonalName = {
FirstName: string;
MiddleInitial: string option;
LastName: string;
}
type Address = {
Address1: string;
Address2: string option ;
City: string;
State: string option;
Zip: string;
}
type PhoneNumber = {
DialOutCode : int;
LocalNumber: string
}
type Contact = {
Name: PersonalName;
DateOfBith: DateTime
Email: string;
Address: Address;
PhoneNumber: PhoneNumber
}
type AccountOpenedEvent = {
AccountId: Guid
Contact: Contact
}
type Event =
| AccountOpened of AccountOpenedEvent
原来event
的一个字段是null
,而不是event
本身。
答案 0 :(得分:2)
问题出在测试/ id
上方定义的contact
和[<Fact>]
上:
let id = Guid.Empty
let contact = {
Name = {
FirstName = "Marcel"
MiddleInitial = None
LastName = "Patulacci"
}
DateOfBith = new DateTime(1850, 12, 25)
Address = {
Address1 = "41 av 8 Mai 1945"
Address2 = None
City = "Sarcelles"
State = None
Zip = "95200"
}
PhoneNumber = {
DialOutCode = 33
LocalNumber = "766030703"
}
Email = "marcel.patulacci@outlook.com"
}
[<Fact>]
let ``Open an account...``() =
let event = Event.AccountOpened({
AccountId = id
Contact = contact
})
let a = [event]
let b = seq { yield event }
Assert.Equal(a, b)
问题是,当独立运行测试时,id
和contact
未初始化,因此即使event
不是null
,联系人也是null
(id
是Guid
,也就是struct
,它仍然具有值)。
由于F#具有结构相等性,因此如果未初始化该字段之一,则足以使一个字段null
使得Assert
在其实现的某个时刻失败。
有一些解决方案/解决方法:
let getId() = Guid.Empty
let getContact() = {
Name = {
FirstName = "Marcel"
MiddleInitial = None
LastName = "Patulacci"
}
DateOfBith = new DateTime(1850, 12, 25)
Address = {
Address1 = "41 av 8 Mai 1945"
Address2 = None
City = "Sarcelles"
State = None
Zip = "95200"
}
PhoneNumber = {
DialOutCode = 33
LocalNumber = "766030703"
}
Email = "marcel.patulacci@outlook.com"
}
[<Fact>]
let ``Open an account...``() =
let id = getId()
let contact = getContact()
let event = Event.AccountOpened({
AccountId = id
Contact = contact
})
let a = [event]
let b = seq { yield event }
Assert.Equal(a, b)
虽然这些变通办法起作用,但令我惊讶的是,在运行测试/时未考虑在单元测试函数正上方声明的变量,并且这些变量未初始化。
也许值得再问一个问题,为什么会这样。 从某种意义上说,这是令人惊讶的,如果可以定义一个函数并返回与那些变量几乎相同的东西,则意味着let也已正确编译,那么为什么变量不是这种情况?