2014-12-28 1 views
3

나는 다음과 같은 시험이 있습니다이 가능 제네릭 형식을 취하는 형태의 더미 객체를 매개 변수 만드는 것입니다

[Fact] 
public void StartProgram_CallsZoneProgramStart() 
{ 
    var zone = A.Fake<Zone>(); 
    zone.StartProgram(); 
    A.CallTo(() => zone.ZoneProgram.Start(null, A.Dummy<ActionBlock<InterruptInfo>>())).MustHaveHappened(Repeated.Exactly.Once); 
} 

그것은 MustHaveHappened 호출로 전달되는 유형 ActionBlock<InterruptInfo>의 더미를 만드는 것 . Zone.StartProgram은 확실히 zone.ZoneProgram.Start 메서드를 호출하지만,이 호출은 FakeItEasy에서 볼 수 없습니다. 그것은 다음과 같은 오류 메시지를 반환

는 전화가 있음을 볼 수없는 이유

으로 오류 메시지에서 볼 수 에서, ActionBlocks의 ID가 비교되는

Assertion failed for the following call: 
    ZoneLighting.ZoneProgramNS.ZoneProgram.Start(<NULL>, ActionBlock\`1 Id=1) 
Expected to find it exactly once but found it #0 times among the calls: 
    1: ZoneLighting.ZoneProgramNS.ZoneProgram.Start(inputStartingValues: Faked ZoneLighting.ZoneProgramNS.InputStartingValues, interruptQueue: ActionBlock`1 Id=2) 
    2: ZoneLighting.ZoneProgramNS.ZoneProgram.Start(inputStartingValues: <NULL>, interruptQueue: ActionBlock`1 Id=2) 
는 다르다 (1, 2), 이는 만든. 내 질문은, 왜 dummied ActionBlock의 ID = 1입니까? 나는 가짜 객체라고 생각했는데, ID와 같이 구체적인 세부 사항을 포함해서는 안됩니다. 제네릭 타입을 거짓말 할 수 없기 때문에 이것이 무엇입니까?

나는 여기에 비슷한 보았다 https://github.com/FakeItEasy/FakeItEasy/issues/402

을하지만 그 같은 일이 아닌지에 대해서 이야기하면 알아낼 수 없습니다. 어떤 도움이라도 대단히 감사하겠습니다.

답변

3

저는 ActionBlock에 익숙하지 않으므로 Id 값을 어디에서 가져 왔는지 확신 할 수 없지만 테스트에서 어떤 일이 벌어지고 있는지에 대해 알 수 있습니다.

먼저, 나는 당신이 Dummy이 무엇인지 혼동하고 있다고 생각합니다. 그렇다면 기분 나쁘게 생각하지 마십시오. 그들은 조금 혼란 스러울 수 있습니다. Dummy documentation에서, 더미는 더미가 특정 유형의 객체가 필요한 경우 FakeItEasy가 제공 할 수있는 객체이다

이지만, 객체의 실제 동작은 중요하지 않습니다.

그들은 거의가 (우리가 나중에에 대한 자세한 내용을 볼 수 있습니다) 클래스 생성자에 공급하거나하는 객체를 생성 할 필요가 FakeItEasy 자체에 의해 사용되는이 방법에서 비 fakeable 개체를 반환해야하는 경우 또는 재산. 최종 사용자가 생성해야하는 경우는 거의 없습니다.

더미는 실제 객체입니다 (그렇지 않으면, 어떻게해야할까요?). 유형에있는 구체적인 세부 사항 (이 경우 ActionBlock<InterruptInfo>)이 있어야합니다. Dummying 제네릭 유형에 대한 제한은 없습니다.

how a Dummy is made에 대한 문서를 보면, 우리는 ActionBlock<InterruptInfo> 때문에 아마이없는 것을 볼 수있는 사용자 정의 IDummyDefinition 가능 (할 당신은? 일이), 그리고 그것은 일이 아니다, 그리고 클래스가 봉인되어 있기 때문에 (fakeable 아니다), 더미는 ActionBlock constructors 중 하나를 호출하여 만들어지며, 더미는 각 인수를 satifsy로 만듭니다.

ActionBlocks에 ID가있는 것 같습니다. 그들이 할당 된 방법에 대해서는 잘 모르겠지만 좋은 ID라면 zone.StartProgram에 제공된 두 개의 다른 ActionBlock<InterruptInfo>이 있고 테스트에서 만든 더미가있는 것 같습니다.

ActionBlocks 문서는 Equals을 덮어 쓰지 않으므로 참조 비교가 수행되고 두 ActionBlocks (생산 코드에서 사용 된 더미와 하나의)가 일치하지 않는다고 제안합니다. 이것이 FakeItEasy가 전화를 인식하지 못하는 이유입니다.

A.CallTo(() => zone.ZoneProgram.Start(null, A<ActionBlock<InterruptInfo>>.Ignored)) 
      .MustHaveHappened(Repeated.Exactly.Once); 

(Ignored 할 수 있습니다 당신은 그냥 zone.ZoneProgram.Start에 대한 호출이 첫 번째 인수 null와 두 번째 인수 일부 ActionBlock로 만들어진 있는지 확인하려고 한 경우

, 내가 사용하는 의미 한 것 같아요 또한 _로 단축 될 당신이 그렇게 경사 인 경우 ignoring argument values에 대해 자세히 알아보기)

나는 두 가지에 대한 우려가 있지만, 즉각적인 문제가 과거의 당신을 얻을 수 :..

  1. 테스트중인 객체로 간주됩니다 날조, zone.ZoneProgram.Start하지 "Exactly.Once"두 번 호출되는 것 같습니다,하지만 난 당신이 처리 할 수있을 거라고 확신하고, 일반적으로
  2. 반 패턴 이군. 일반적으로 테스트중인 생산 코드에 가짜 종속성을 제공합니다. 나는 그것이 작동하지 않을 것이라고 말하는 것이 아니라 때로는 혼란을 가져올 수도 있습니다. 그러나 현재의 문제가 해결 된 후 다른 날에는 문제가 될 수 있습니다.

조금 도움이 되었기를 바랍니다.

오, 문제 402에 대해 질문했습니다.이 문제는 인형 생성 방법을 제어 할 사용자 지정 클래스를 정의 할 때 사용자에게 더 많은 권한을 부여하는 것에 관한 것입니다. IDummyDefinition 또는 DummyDefinition까지 확장하지 않으면이 시점과 관련이 없습니다.

+0

자세한 답변을 보내 주셔서 감사합니다. 나는 인봉 된 강좌가 이런 식으로 머무를 수 없다는 것을 몰랐다. 그래서 나의 후속 질문은 다음과 같습니다. 테스트 관점에서, 더미를 사용하거나 .Ignored 기법을 사용하는지 어떻게 알 수 있습니까? 두 경우 모두 유형이 필요하지만 객체의 실제 동작은 중요하지 않습니다 (회신에서 더미 문서 참조). – Anshul

+0

테스트중인 객체를 반 패턴으로 위장하는 것에 관해서는 왜 그런 경우입니까? 만약 우리가 단지 객체의 "배관 공사 (plumbing)"를 테스트하여 연결되어야 할 부분이 메쏘드 호출의 측면에서 연결되어 있는지 확인한다면 어떨까요? 객체를 위조하지 않고 이것을 테스트하는 방법은 무엇입니까? – Anshul

+0

'Ignored'는 호출에 전달 된 인수가 중요하지 않을 때 사용됩니다. 일반적으로 호출 일치 의미론의 경우 [Argument Constraints] (https://github.com/FakeItEasy/FakeItEasy/wiki/Argument-Constraints) 기술을 사용할 수 있습니다. 한 번 생성 된 더미는 다른 것과 마찬가지로 객체이므로 'A.CallTo'에 제공하면'Equals'를 사용하여 실제 인수와 비교하게됩니다. 비교를 "true"라고 말하고 싶다면 답에 대해 신경 써야합니다. 따라서 더미는 나쁜 선택입니다. 일이 생기더라도, 왜 그렇게 명확하지 않을 것입니다. –

관련 문제