2011-06-17 10 views
5

Al usar invariantes de clase, los contratos de Código parecen inyectar código en todas partes. Cosas como estaContratos de Moq y Código

[ContractClassFor(typeof(IX))] 
interface IXContract 
{ 
    [ClassInvariant] 
    void Invariant() { ... } 
} 

[ContractClass(typeof(IXContract))] 
interface IX { event EventHandler b; } 

var a = new Mock<IX>(); 

a.Raise(x => x.b += null); 

un error con un mensaje de error

Could not locate event for attach or detach method Void $InvariantMethod$(). 

Alguien sabe de una solución?

+0

¿Qué estamos viendo exactamente? –

+0

Se agregó más código – jameszhao00

+0

¿De dónde vino ese atributo 'ClassInvariant'? – Jonn

Respuesta

3

Esta unidad de prueba "pasa" cuando se ejecuta sin excepciones electrógenos:

[ContractClassFor(typeof(IX))] 
class IXContract 
{ 
    [ContractInvariantMethod] 
    void Invariant() { } 
} 

[ContractClass(typeof(IXContract))] 
public interface IX { event EventHandler b; } 

/// <summary> 
/// Summary description for UnitTest1 
/// </summary> 
[TestClass] 
public class UnitTest1 
{ 
    public void MyTest() 
    { 
     var a = new Mock<IX>(); 

     a.Raise(x => x.b += null); 
    } 
} 

No estoy del todo seguro de lo que está pasando y cómo se está compilando (o transcripción) de lo anterior, pero no lo hago cree que puede tener el atributo "ContractClassFor" decorando una interfaz, y ciertamente no puede tener la implementación "{...}" en una interfaz. También necesita hacer que su interfaz IX sea pública para simularla (o interna con InternalsVisibleTo() proxy de castillo en sus propiedades).

Esperemos que esto ayude, pero no dude en actualizar su publicación con un nuevo código si esto no lo lleva hacia lo que está buscando hacer.

+0

También hay algunas cosas malas con sus cambios. IXContract debe ser abstracto, no solo interno. El método Invariante no es apropiado allí. Tener uno no es realmente posible ya que está comprobando las propiedades y los campos de la implementación, y no sabe cómo todos implementarán la interfaz. Además, esta clase de Contrato NO es la implementación real, está allí como pegamento para permitir contratos en las interfaces. Además, la clase DEBE implementar la interfaz IX. Mira mi respuesta para ver qué aspecto debería tener. – Andy

2

Tu código es incorrecto. Debería verse así:

[ContractClassFor(typeof(IX))] 
internal abstract class XContract : IX 
{ 
    // Invariants belong on your actual implemenation; interfaces don't dictate implemenation so this isn't appropariate here. 
    // [ ContractInvariantMethod] 
    // void Invariant() { ... } 

    public event EventHandler b { get { return default(EventHandler); } set { }} 
} 

[ContractClass(typeof(XContract))] 
interface IX { event EventHandler b; } 

var a = new Mock<IX>(); 

a.Raise(x => x.b += null); 

Observe que la clase Contract es Resumen interno, y que ahora también implementa su interfaz. Invariant no es apropiado allí, ya que eso es para detalles de implementación; no sabes cómo las personas implementarán tu interfaz, así que no la pongas allí. También el atributo para métodos invariantes es ContractInvariantMethodAttribute.

Cuestiones relacionadas