O Class Foo é implementado em MyApp e MyAppTestCase. Um dos dois será usado. Qual deles é indefinido

Recentemente eu comecei a testar a minha aplicação. Este projeto (no Xcode4) foi criado sem um pacote de teste de unidade, então eu tive que configurá-lo. Eu segui os passos a partir daqui: http://cocoawithlove.com/2009/12/sample-mac-application-with-complete.html E ele estava funcionando bem para classs simples, mas agora estou tentando testar uma class que depende no outro e no outro, etc.

Primeiro, recebi um erro de vinculador, então adicionei arquivos *.m ao destino do caso de teste, mas agora recebo um aviso para cada class que estou tentando testar:

O Class Foo é implementado em MyApp e MyAppTestCase. Um dos dois será usado. Qual deles é indefinido.

Eu me pergunto por que isso? Como posso resolver isso? Talvez eu tenha perdido algo ao definir o alvo do teste de unidade?

Editar – a solução

  • Configure o “Bundle Loader” corretamente para $(BUILT_PRODUCTS_DIR)/AppName.app/AppName

  • Defina “Símbolos ocultos por padrão” como NÃO (em Configurações de compilation do aplicativo de destino). É aqui que os erros do vinculador vêm, porque é SIM por padrão !. Eu tenho lutado com isso por tanto tempo !.

Fonte: Linking error for unit testing com o XCode 4?

O Class Foo é implementado em MyApp e MyAppTestCase. Um dos dois será usado. Qual deles é indefinido.

Eu me pergunto por que isso?

porque ambas as imagens (o aplicativo e o pacote de teste de unidade) definem a implementação da class. a class é carregada dinamicamente no tempo de execução do objc. o tempo de execução objc usa um namespace simples. como isso funciona:

  • o binário é carregado, começando com suas dependencies
  • como cada binário é carregado, as classs objc registram com o tempo de execução objc
  • Se uma class com um nome específico é carregada duas vezes, o comportamento é indefinido. uma implementação de uma class (com nomes idênticos) pode ser carregada no tempo de execução do objc.

O problema típico aqui é que você retornará uma implementação – seu aplicativo provavelmente falhará quando o tipo entrar em conflito (quando a class não vier do mesmo arquivo de origem).

você normalmente evita isso renomeando uma class ou exporta a class em uma imagem. renomear a class obviamente não se aplica ao seu caso. você tem um arquivo Foo.m que está sendo compilado, exportado e carregado por duas imagens quando deveria estar em um.

isso deve ser interpretado por você como um erro de linker de símbolo duplicado. mesmo que a implementação seja o mesmo arquivo de origem (e a implementação é a mesma) – este é um problema que você deve corrigir.

Como posso resolver isso?

Se Foo.m é uma class do aplicativo, você deve remover (não compilar e vincular) Foo.m do teste de unidade. se for parte do teste de unidade, não compile e vincule-o ao destino de teste de unidade.

em seguida, siga as instruções no post para vincular / carregar seu teste de unidade ao aplicativo. está nesta área geral do post: onde “WhereIsMyMac” é o nome do aplicativo que você está testando. Isso permitirá que o alvo de teste se vincule ao aplicativo (para que você não receba erros de vinculador ao compilar). A parte importante é que seus arquivos de teste são compilados no destino de teste de unidade (somente) e as classs do seu aplicativo são compiladas e vinculadas ao aplicativo. você não pode simplesmente adicioná-los – eles vinculam e carregam dinamicamente.

Talvez eu tenha perdido algo ao definir o alvo do teste de unidade?

Do artigo que você vinculou:

Nota: O alvo de teste é um alvo separado. Isso significa que você precisa ter cuidado com a participação de destino. Todos os arquivos de origem do aplicativo devem ser adicionados somente ao destino do aplicativo. Os arquivos de código de teste devem ser adicionados somente ao alvo de teste.

a parte que você errou é provavelmente o link e as fases de carga do pacote de teste de unidade.

Se você estiver usando Cocoapods, seu podfile precisará apenas das dependencies na seção para o destino principal, não para os destinos de teste. Se você adicionar dependencies duplicadas para os destinos de teste, receberá a mensagem de erro do OP.

 target 'MyProject' do pod 'Parse' end target 'MyProjectTests' do end target 'MyProjectUITests' do end 

Para mim, tudo que eu precisava fazer era desmarcar a checkbox de seleção que faz da class Foo um membro do alvo de teste da unidade. Não deve ser um membro de ambos os alvos e deve ficar assim:

Associação Alvo

Caso você não consiga ver a imagem, é uma captura de canvas do painel “Associação de destino” do Xcode. Existem dois alvos: um com um ícone de aplicativo “A” e o nome do teste. O outro é o alvo de teste de unidade e tem um ícone de teste de unidade:

 Target Membership [X] Foo [ ] FooTests 

Para mim, isso aconteceu porque eu implantei no dispositivo e, em seguida, no simulador, já que tenho o NSZombies ativado. A solução foi mudar para a configuração do simulador e fazer um Produto -> Limpar, em seguida, mudar para a configuração do dispositivo e fazer o mesmo. Erro foi embora. Tem a ver com o cache de compilation.

O motivo é que você substitui RUNPATH_SEARCH_PATHS da RUNPATH_SEARCH_PATHS de RUNPATH_SEARCH_PATHS do seu RUNPATH_SEARCH_PATHS do aplicativo definida em outro destino.

Solução:

Vá para o seu Destino do Aplicativo e encontre a configuração de construção RUNPATH_SEARCH_PATHS e use o sinalizador $(inherited) para ambos: Depurar e Liberar

Venha através dos mesmos problemas, Minha situação é Classe NSNotification é implementada em ambos / System / Library / Frames / Foundation.framework / Foundation, existe algum cara se deparar com o mesmo problema, qualquer direção ou aconselhar será appriciated.